///////////////////////////////////////////////////////////////
//  Copyright Christopher Kormanyos 2002 - 2011.
//  Copyright 2011 John Maddock. Distributed under the Boost
//  Software License, Version 1.0. (See accompanying file
//  LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
//
// This work is based on an earlier work:
// "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations",
// in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469

#ifdef _MSC_VER
#define _SCL_SECURE_NO_WARNINGS
#endif

#include <boost/detail/lightweight_test.hpp>
#include <boost/array.hpp>
#include "test.hpp"

#if !defined(TEST_MPF_50) && !defined(TEST_MPF) && !defined(TEST_BACKEND) && !defined(TEST_CPP_DEC_FLOAT) && \
    !defined(TEST_MPFR) && !defined(TEST_MPFR_50) && !defined(TEST_MPFI_50) && !defined(TEST_FLOAT128) &&    \
    !defined(TEST_CPP_BIN_FLOAT)
#define TEST_MPF_50
#define TEST_MPFR_50
#define TEST_MPFI_50
#define TEST_BACKEND
#define TEST_CPP_DEC_FLOAT
#define TEST_FLOAT128
#define TEST_CPP_BIN_FLOAT

#ifdef _MSC_VER
#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!")
#endif
#ifdef __GNUC__
#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!"
#endif

#endif

#if defined(TEST_MPF_50)
#include <nil/crypto3/multiprecision/gmp.hpp>
#endif
#if defined(TEST_MPFR_50)
#include <nil/crypto3/multiprecision/mpfr.hpp>
#endif
#if defined(TEST_MPFI_50)
#include <nil/crypto3/multiprecision/mpfi.hpp>
#endif
#ifdef TEST_BACKEND
#include <nil/crypto3/multiprecision/concepts/mp_number_archetypes.hpp>
#endif
#ifdef TEST_CPP_DEC_FLOAT
#include <nil/crypto3/multiprecision/cpp_dec_float.hpp>
#endif
#ifdef TEST_FLOAT128
#include <nil/crypto3/multiprecision/float128.hpp>
#endif
#ifdef TEST_CPP_BIN_FLOAT
#include <nil/crypto3/multiprecision/cpp_bin_float.hpp>
#endif

template<class T>
struct has_poor_large_value_support {
    static const bool value = false;
};
#ifdef TEST_CPP_DEC_FLOAT
template<unsigned Digits10, class ExponentType, class Allocator,
         nil::crypto3::multiprecision::expression_template_option ExpressionTemplates>
struct has_poor_large_value_support<nil::crypto3::multiprecision::number<
    nil::crypto3::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates>> {
    static const bool value = true;
};
#endif
#ifdef TEST_CPP_BIN_FLOAT
template<unsigned Digits, nil::crypto3::multiprecision::backends::digit_base_type DigitBase, class Allocator,
         class Exponent, Exponent MinE, Exponent MaxE,
         nil::crypto3::multiprecision::expression_template_option ExpressionTemplates>
struct has_poor_large_value_support<nil::crypto3::multiprecision::number<
    nil::crypto3::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>,
    ExpressionTemplates>> {
    static const bool value = true;
};
#endif

template<class T>
void test() {
    std::cout << "Testing type: " << typeid(T).name() << std::endl;
    static const boost::array<const char*, 101u> data = {{
        "-9."
        "71360659712083391437631022096936715962104815777147739346439739644168480837178969413799829610404829247283169084"
        "501281105e-1",
        "-5."
        "95431113317256105006804890684659010940293672390817519158205264611725147142085353698349092164137652363446368483"
        "953564682e-1",
        "5."
        "09924118934356013545988500545586843463766955556781588535384546070893806324487181574368899833574915659357543038"
        "822935347e-1",
        "9."
        "90602974910637417521410554344955057938063175873799034495811832851567842600306335485818201417146475654562543760"
        "051881571e-1",
        "2."
        "57755634110962773819397192502372718147953063328591480930319110437537556577887190430547163274290595074462686853"
        "519200826e-1",
        "-7."
        "90852129665907861812449876176102241731921451584589870529143390612597378289323905030142878920134443274067663564"
        "142249906e-1",
        "-8."
        "70636054394434218558219672958497111094237434037462776135170928197514857325641761722162169311905082223410873872"
        "693125021e-1",
        "1."
        "16142192225871586802402588799179588339908282696987123538816621894316618250692422106879105583060486278819650782"
        "761165055e-1",
        "9."
        "60641850565339311654365605083646127348817546384991780755200411966145627086231307074524787693440076802209868233"
        "548778731e-1",
        "6."
        "28318825240308217440049590303028869715272770671179428040549526344092598897275498972932981684079339892035243316"
        "790587027e-1",
        "-4."
        "73718579778960595001132927360485548840577209745936881040433718918629103032639945353908537818475936329314134212"
        "199346978e-1",
        "-9."
        "95432766494621395340223548609251497842694553405493731879049259799325119533316838972006879914623359183523219011"
        "870805961e-1",
        "-2."
        "97704078652633309130390182393607392013126109733352620573058826659738026681661456497779386104992235762190242017"
        "128767206e-1",
        "7."
        "64723391125286889782047394187107836056829439952009227196240883193721606229047061163517791688110517783506991004"
        "016374431e-1",
        "8."
        "90335717074674250432504838435892622513509178529392798127561987551398090841490265311069534613651712468228001675"
        "091153605e-1",
        "-7."
        "47469618974513669394515485690188234127771130501791709462887130373371023385813212165673231177548426835629029005"
        "547008861e-2",
        "-9."
        "48261778982069330544079494960981900232314056127899219497335245577354566418258722147558010380033694835705634428"
        "764954401e-1",
        "-6."
        "60119969404606610211922488494059074732492583049845598285779387022002845776084527598443564095143849120847643366"
        "330179739e-1",
        "4."
        "36693827009658961576344650626557410722590226545637608661764593658572210930294024902150766064738444736422263939"
        "746970132e-1",
        "9."
        "98541130824430070642243744636010968399851408459030982248969144276197147611376115185206245742327729890090526273"
        "555800490e-1",
        "3."
        "37137695943362070360548307779555944485385294617304662646987679063953108310365389494460188124285214040163147170"
        "304540339e-1",
        "-7."
        "37272196933518190054375156317136276073182897209685319124536092629865074949247291797880288692223977281455156619"
        "510259042e-1",
        "-9."
        "08495699506960201290293288218820500948312195353635174830883006841931398581001427066173033535720385301624330783"
        "999899511e-1",
        "3."
        "32224697427099307204044509056982627738295866011152619834749776109067529453431741767996787924292629814505731320"
        "175556430e-2",
        "9."
        "34241854135599266375493853147210486293657026766576383005045752264274587199837314096798394557243705656211732557"
        "069413970e-1",
        "6."
        "90779551281016826784976005137338585011513089446563025258584317423906941741640583083551185645679047405447557105"
        "684226754e-1",
        "-3."
        "98913888475082839741071010629509607776766095858433376450534753556286110518195743624946499527251336022805096741"
        "714382999e-1",
        "-9."
        "99922692526403520897313527841668431397204867244750030781062964701898557028332255650446046614062333174844253917"
        "288331438e-1",
        "-3."
        "75988292423704532504216998833472116186771022412627192871974303806891208635376610998425108046077306043945435504"
        "842144332e-1",
        "7."
        "08546019140379445669962535829318394094758212505515423960726677977484727061149949358051741627739138448760095710"
        "063342839e-1",
        "9."
        "25084597170819667485373176055260044057716794391569156042799693611964098948722923916237050181882167134906470192"
        "542857299e-1",
        "8."
        "35947487571472125423673177137150279693224632368449469153892167972732129345714981936363891382927399742266512920"
        "038864004e-3",
        "-9."
        "18606321039298722214219289469027246078943851192917449117591801249272620492502932760495762195965214412326830491"
        "755901723e-1",
        "-7."
        "20244550473164405555518647469765134103488938825118543602681358279149452868549672550326500728323814331193184035"
        "259160414e-1",
        "3."
        "60444097985855629825697367385029316833790934188475151408740160657889784929257301330229580694580194294034115152"
        "177674537e-1",
        "9."
        "99575062430677992414643463029115424067356090568060307410717467085018957489304987413609313388961297483138454662"
        "118061646e-1",
        "4."
        "14188682766963304833862149212585018360876819555612195218295874225032162838027842720351664698295767693697842043"
        "579048219e-1",
        "-6."
        "78594534657286312316409269272929566493548786915986771929001823358451551885758307761400157853363173388867780400"
        "090112946e-1",
        "-9."
        "40073722462713282312837596921874850901167502371739429501407718251639587081137893231736511487958940802467918593"
        "519005653e-1",
        "-4."
        "99269632411748222821310824324558181913141458235676771744322439351386139493233963671531219603373207564905654915"
        "871172017e-2",
        "9."
        "01382218619061521491363679812206948759377256420255657634443270431495336446996377562469573885297156497163691224"
        "107230524e-1",
        "7."
        "48464012406957686684753003872919309910943477238245908909177973105841950470333390670719219379167068809799710776"
        "770734833e-1",
        "-3."
        "21350982331168500558883709193541886146178412146971245706190880193067020283050714591560922441331235332970961845"
        "050217575e-1",
        "-9."
        "97498841702838239659412520756556451623238132913559678626409839807628110807613195403956929948379909495726426243"
        "705794281e-1",
        "-4."
        "51672806064485973599605876288778011355969815150135195358334589946828629430271875346142404286368814526016297993"
        "583170592e-1",
        "6."
        "47469539349743367777844577149239337681085253251300560380374646379682072633705733561446355539618404778987844138"
        "766238618e-1",
        "9."
        "53437154306238691456130012770111782377503876017231780889420296856266641153714110120975772709549811845909173386"
        "912105405e-1",
        "9."
        "14081116365893107669584386407698218216480671014671832303147213716318806206478591012619084058741626713939006968"
        "851852873e-2",
        "-8."
        "82599332954202005638662236444958997569939600897565089251125658458817750203393016337212996488633688567918453254"
        "294067039e-1",
        "-7."
        "75389136447631492669594511701990356678047393586968390929688701894781023967621486245394406725747074772996680491"
        "766725244e-1",
        "0",
        "9."
        "21877670451674413245307018032333288624288893879527153976730741889055419244554390143014969580425598422296522787"
        "223865492e-1",
        "7."
        "14420247379307162288182477560228852605155250738051326022559557923361829606843109334201812861061126243914893718"
        "333771523e-1",
        "-3."
        "68229061503980158220203193441625324286779814470455045264018328963975686564161509474566417124652588774892207244"
        "798533238e-1",
        "-9."
        "99783810945210864429782835782052003838999970584938136857974918523615732378678641269300999292060748749245257644"
        "847852880e-1",
        "-4."
        "06565491434208630299086167510578859920684132980243005899494321151205958987020300473732138517681916554185382528"
        "057861016e-1",
        "6."
        "84710967469127345624707128760638003100107237269026812211460044517359789036617753689648451870956943571853410785"
        "082804567e-1",
        "9."
        "37190534692875414284475879207349713030454322911019395907169592096165438597133651606167760904128838721803617281"
        "109050826e-1",
        "4."
        "15761692057244148543310701200534576325308397337003695681679007540324069366547327722258885686349619359915993749"
        "152386902e-2",
        "-9."
        "04970579658619470380865991258110513843850446973806499697900678159194774744593408797468966041695053471205276923"
        "200577190e-1",
        "-7."
        "42894062146919717307486895770712177633720181625852464705801879158549930143011385755502810839808877188169347497"
        "140463278e-1",
        "3."
        "29255843672460745277513964057060067396377984587222455665841087186879420769340447084849343957766905952270152874"
        "052907066e-1",
        "9."
        "98054859318969984153930327705164465077718593220578997216979734167429154849012382322757855259404199572095265136"
        "279871773e-1",
        "4."
        "44198837297768694342150710437773511448850303134514239359160353596186338967438818161771076138440975975069051604"
        "632938785e-1",
        "-6."
        "53817599431343721060913145888825198919543068369083977787231740776950274433927919565042681494795499030972133972"
        "973154991e-1",
        "-9."
        "50882691455803790808811011811129940528171185220498569922200361836899859377942311459807744784166538095896117442"
        "350480286e-1",
        "-8."
        "30804396823694462619418608693397504202900045660409997788297791645107264729830105800672434941805906654953509298"
        "579082883e-2",
        "8."
        "86498500176738212245618093138553877114943127333459437678466772704535139826656179981455385901664422134192971441"
        "152486596e-1",
        "7."
        "70083171278361495868782270594413506070341191348346709317329019377797940394556787220273230008072684372906392335"
        "068211595e-1",
        "-2."
        "89713235318575682157337623325710322388267200178020040738121279630672170355171163891332847251952971324782327373"
        "734923025e-1",
        "-9."
        "94599945986602107902462030221489305674036413322184167100620086215068494963807086265519051279456167270901961176"
        "645890910e-1",
        "-4."
        "81064018790479216363003919039401079745827607566793090566247167201506427394383426836725220489510187378030886775"
        "425254046e-1",
        "6."
        "21793567954698234151923123976248746751871911018984490371928031737872104124834908200003970971778452547150523318"
        "639635937e-1",
        "9."
        "62930462544790791995256817531759605974030310743258985429278608944994805716203043054967792555227147404499205611"
        "680348343e-1",
        "1."
        "24441037037160425420824052419427892644210865386492893504553391973646623439822770473194845274620957661128504291"
        "608680469e-1",
        "-8."
        "66493376243885476034533210550037276824055111358129259572484897399197578809821587005093985112028866251515011805"
        "996119334e-1",
        "-7."
        "95940555954229526911811786010975888490876487056728372525209250018208474961217211282867562886053609351620626802"
        "054272020e-1",
        "2."
        "49669618482792917975718339302754781070461300705127317300546100189317933291972223791458678771914034385073586648"
        "459580423e-1",
        "9."
        "89425045617789945796335206411736550560149597573171983909624851636680028232543261568285131480585113303281176722"
        "731984359e-1",
        "5."
        "17097284014384149171097163430722725596083616428334032893201431916692899725128152827282357887267679461332587145"
        "165393473e-1",
        "-5."
        "88694253013035419947972745515246684318073372460957150709985237608958241550865774225576562359889367149484593966"
        "586261944e-1",
        "-9."
        "73313013442224866478107643999632554759604190263325143130961313777287157745245701134838602677190253924612391775"
        "436901182e-1",
        "-1."
        "65586435334914172055850479429458408174448669771862313204835451683387762284114799645762688524058144409210946183"
        "564694437e-1",
        "8."
        "44989803230758608979729460217254170202748876564967551526138387646760352687916491884649142029664716335759879232"
        "648284164e-1",
        "8."
        "20421500340164168068753907367027481963552257850283600606773656660614708517253273174848291641569969886126754639"
        "035754147e-1",
        "-2."
        "09194241612317592929856274655591551278574667482924447651723415490434554354833563537792618079275726893013991849"
        "104465053e-1",
        "-9."
        "82539107299636472172005507105476251789057582568202763534005396813858490465264145708502581273803767931004018272"
        "989858624e-1",
        "-5."
        "52236319725534543207688775430217404447704139560595336544456138148662731976576062425879410116209671353021251780"
        "801885578e-1",
        "5."
        "54576894095302137473562870411642498454159878739464625116831971740997730359915227524075717328436463081497500485"
        "416831879e-1",
        "9."
        "82012389338213987427432686899213579991770436451929205950504261612336440523069987734051927060071228336651935114"
        "247230018e-1",
        "2."
        "06445480789661722781085666935934466710665000093111315471318244086154187788240397407764949071589419997001126229"
        "699279918e-1",
        "-8."
        "22024967814241172490083350373664443948382772873119098939533117836179462362265599942085298240078400862839510315"
        "401568501e-1",
        "-8."
        "43483668915081157881609334416452212500481988371373212797897630926101856989377353686006695443683562952698091745"
        "372956064e-1",
        "1."
        "68357099807987317797633647903674089665368628422558854222230995142941489911909308417314277825877040168111682241"
        "442337249e-1",
        "9."
        "73954039060780508698548127540108987785881109985102169990241290387386676882934112332475075476604334818263785540"
        "220696343e-1",
        "5."
        "86420359093869515237687266954561200160006212641211187483350874672859136679499954407470935299385535928011115437"
        "979374327e-1",
        "-5."
        "19500491219840443397382144913775579016253538466887540765306393159738082663675375499840773403952929977354698339"
        "617261390e-1",
        "-9."
        "89013546180296021750901758474634735102493497248279924875522015911873550276888689676425102442986261848126775556"
        "194306727e-1",
        "-2."
        "46947514812703938169894550153319655995779907820829748198209521180129269232387596803077057086642606505827139155"
        "491603712e-1",
        "7."
        "97638583669534812597149574893980942155226403291812660315816507318428697361476484505958849067790885048775312980"
        "075497096e-1",
        "8."
        "65087179683067252708187359165577777305998628817518314353161876891989239932835217904989326717355654871984067712"
        "207255166e-1",
    }};

    boost::uintmax_t max_err = 0;
    for (unsigned k = 0; k < data.size(); k++) {
        static const T euler_gamma = static_cast<T>(
            "5."
            "7721566490153286060651209008240243104215933593992359880576723488486772677766467093694706329174674951463144"
            "7249807082480960504014486542836224173997644923536253500333742937337737673942792595258247094916008735203948"
            "165670853233151776611528621199501507984793745085705740029921354786146694029604325421519e-1");
        T val = sin(euler_gamma * ((100 * k) - 5000));
        T e = relative_error(val, T(data[k]));
        unsigned err = e.template convert_to<unsigned>();
        if (err > max_err)
            max_err = err;
        val = sin(-euler_gamma * ((100 * k) - 5000));
        e = relative_error(val, T(-T(data[k])));
        err = e.template convert_to<unsigned>();
        if (err > max_err)
            max_err = err;
    }
    std::cout << "Max error was: " << max_err << std::endl;
    BOOST_TEST(max_err < 5000000000uLL);

    static const boost::array<const char*, 51u> small_data = {{
        "0."
        "01089064630743739902856319116025283959992923281497092220866490923749471618148421571764477693304441890320791991"
        "20635941590991334909796343448119369251444477259483053532570425995644048854343497601210097978167241423182437383"
        "64307036155852011004353462651092012819894667485840322627440332163428546845499107471983896711023161969130462687"
        "924045508477090891879273259947713367290982391204265694893491531721581439",
        "0."
        "02975439400052097214138026770567725635370299616985841416844527218177733896286655284708480054408674333813019521"
        "00050026608819575845679787704850563220864723288969880887218997282582241299359891808574370734127309030709835821"
        "29359565450458299328041955729258476583848159389714290107649243089149974776893563078190705561325124542669960182"
        "002956940545214147678093802442811362846262655415145897575707676223535749",
        "0."
        "04860754948595027759689273751438643634234576398271158524070718139962965653841137425728738193533514318422431877"
        "21711023955474396860987003977693820172468804834997266239408478992486726740585369601747816070268311797476665784"
        "09652706258144824223984222166054906200545742529109280684338471151324297260728531703391138048386255369813614900"
        "08602432476302086066307320875870985443111858828925332085101376920451257",
        "0."
        "06744340126632979236558326841897702258708980659586081879024629310446357618443609683311190306480155237998836222"
        "46331980524902345176563184740055687090487103081239670821032352302015163788348557643487405054701769124665871399"
        "88300259624310153055247378188811239571439869254255368050758213303082097176168650573121101094016896349982672715"
        "603054645687782535250201448606757920212668324401846105554332382154705308",
        "0."
        "08625524400417560419964578622668386565013076463814293901055424591917229956058363426206776946588694468988333339"
        "40991207659647710920699387536892536865430178710635879884372350575141317605876495046701179338144869421875897066"
        "55157340717185354058186603027300571692666150552274324933749082047517987509942119060274537912867956274549119040"
        "817359639741746006374702951412541338483858389306953539029174581171144916",
        "0."
        "10503638090893519164596691292161072193010174143933600597680115817738720676321226654184308409972393036413684625"
        "87429471349075327126138098755252823666068862410847412446903444407662731567423438557860811139811224227276272284"
        "90838017738186893421749078583738831922208276876183210850079173879515326735992672110357853079475156388107356219"
        "64273183425401191468313574763898720597251843424536611952986478638938787",
        "0."
        "12378012612096459891996422671239906394195356627713556749926735466337892925173796651675302282473738808218327028"
        "58960689482572878482354060506531750664590056598016190128711641020804954281879699417120389095276165147018783417"
        "36446515080250889700348000672451317596550031641271610580846828319064069414736503958735779259014195365408284680"
        "01386512234321890242266327761400155849351025221609783793228816606096155",
        "0."
        "14247980709161433833827358255114404185333478069639957369769805221957506649654851981837061160249376538785737485"
        "77724881781272059253759726325270642206643813752201114856662586155220938062032508044161850325750679898159855989"
        "73317545553356882841114177972118883811414455225367395427652079365162979070769238998402168641917770390286228860"
        "76254231994264908278499537587536902686114072117102531777746791366147472",
        "0."
        "16112876695857673825462942280040873226725445145336882995544646098546697397681955191516861690559627281570477802"
        "64768315324982873176106271848742410432515208876322077683124856648636329944844379526610456855518697769593980342"
        "07935752041461246978327937738704490823779640296582837419107418045507625113798948905891326584503686093770056303"
        "22641674351408014813725947288936865021810537922503050280596331958949813",
        "0."
        "17972036691564914131189073707203611766536704952071818203835281740755093560444625679032703078557333645546302532"
        "20067472978166383807510519633269502424650904283109555305080476766378801411317799193825222512022830273422863278"
        "70820724806897193222992470908872297312601351658195957973926651066425953594330943867432148529299651049462761959"
        "24300495453775467378376551444126292108291215861133471208854009513721707",
        "0."
        "19824798857606934571352609051549058593435535174283382080060738672122306773474119459815363636791069253463660528"
        "11402204167478056579865526564007266932981980223448354544408542647066123395803066884432667476881545631587986837"
        "62527223695746944115910805125276831457742142151932689925089385621096698431372702384549050915551797563745124577"
        "42554641355319960601765568460966738628365652972463731882673979926092423",
        "0."
        "21670503632858197042231878766421697174743460257666062446431767504606577312036112174702416761820416751121719744"
        "14875203007374497968642376196256262296063879827128970901451226217571636202438144440234868076467587220541438440"
        "14968225431713440530264842679050075131048543299093018508757815039903254399017381110646565640453011603238726043"
        "2178319507278340110997943206401370789106214680733463126804159766688178",
        "0."
        "23508493968539701289801441539326267060915175918342580386836036980227948313782327655061004506711767031388143537"
        "08182698603099055770792220360334998485180917378840210175651001704663963152828269840485765444427950959187367820"
        "83184840363370408378445391908636153108729844552619736478976678433022417737955923550851182735926713486022403821"
        "53223466391512738221253451636183066773121830262978729780866153048605159",
        "0."
        "25338115562120475426791611735821512271036721877699715435823882597847951553326227795478394590166472902500360057"
        "12168909799523370471647322112833886051217950625710683025675691585734514265087749450457714578451290681140064635"
        "29150164039575329053231840611010689221838881178156130540257000028380645813443582252904379796234042084185001184"
        "6648265787470508569124672250211852546600514370101687713861131209463861",
        "0."
        "27158717090241435065755609312085387589073221253701701142877476904254125053252466469600403650634482409879186635"
        "71700237008909707004582118243264223261842794448973213335999689981298072210701112695785057621047667906916256125"
        "71679216276035366039433422687707275246903324002554085876540945123833498575967757777258889822775592819825714876"
        "56535560758087235441872907962373375423740325723506626374882319859924962",
        "0."
        "28969650440578692965912855479777150523900698183973110358010443581781966348171378962307935462457921708108325003"
        "56667384985164030457101920011328040674455144514820034155450114117444453000832926282678616008093130905752867371"
        "15079348226594568611631976188137270621794535554604001698582339233582386078753065238667675362433610493065455966"
        "78120228677505849040202788510059415993219975440657979707947898632705847",
        "0."
        "30770270942563778634443222550824378057595253208974144909939396933701715445493088586920897452838893301853350676"
        "95540035719783877382314069620964957382838247745471198680615449799891292626538849422845998832352454875087070208"
        "33392859694683918465333485898515202629907208436701487902110092360636221942823155408014672166256665056636994805"
        "92080398449845511909092071640909885054719301078547683325662349532658001",
        "0."
        "32559937596878634249263192973385963275552570142977727375619908690982968889531407133936548327912894149757305868"
        "45439400253138582034104586316114669515190826955362912137270069583337396853351066126585473894794068972181223081"
        "95754908742112790072898283699645832736763933989810640154592849829700481746490945496311093129411886918381189556"
        "83939990881732219088392629316401227525790752712758279892546851835776728",
        "0."
        "34338013303643689435259984865624959352259286039436985939426483729323987764837568376066164703227630278807584950"
        "27862603576339916417742989432242586623615033689807957325815783307477228735431004967602956656973799505449901851"
        "86994509460566265364798228527581638485289200782477893496058989762904842840189843556966481909677018494645712862"
        "57873661615051036433297599097073117151941857301740816310919312668936753",
        "0."
        "36103865089217782674224266392907326208964452822379102503439414768728197653534265911503054023760783622236800804"
        "79447078563173799314318007155022372880198490485262316039723083964462907778263094948633910476000856693501323419"
        "57357770705821066614232193793745229415228323311861479053329777260437957370082189092260259622948805418679644194"
        "24128310806148008435847967256901208159302482322730929744194185143496647",
        "0."
        "37856864331529191294683302986737462527422720295203122486985051910813389831630458742420433021640718832999264813"
        "67493815727337529059278875313399674185996525803427342865739986315948851943411309386304217926164920258497982834"
        "74951613917805924334548094206326051781059580496309385325681567898069466293093757903435857918847558664002954706"
        "51281289167454617624179556306285775538273640784278475358303871406797294",
        "0."
        "39596386983857554895577100112509216027806053013084575955698650981320612512273211286811283498352122125088102462"
        "99921462519655630208347321575504292305860152320513799100372630595769065936291506594220617567642210250680560302"
        "66245993103681513176770256335737879473390342421986658155401572295806217890247341488393380719092096168791219147"
        "0152974845756609418554739641361171541363409996648143043979357302190703",
        "0."
        "41321813796987028521091431473013916161596830805293649687424341688961507413716621591649879163383882641673238540"
        "68278262695935895500221600331672634462361362680995099344921445707129296112618876186021400766206734519354539365"
        "31917424976461931896778906579929646601399244630870727040969697489953586054590640767755406799521821000135842738"
        "77612509536257834358450242426357122974687246428904315337788603554112487",
        "0."
        "43032530539651581726649227346608528709372859200683817125277384462849187532000288969537766724897319030479860713"
        "59145993286650825490486945642308831294597094368645042558990722727535818647331064445835339210769343947527254418"
        "17265205662213338460082200087020704606267393423100391481066497267196657281698197143331726050163134990672279537"
        "67878741853545763313707499816244740855778447731454065384788859848319503",
        "0."
        "44727928217193967651655712666040617006236300257644793444619887007723922383970962870988815495150987337761018019"
        "12879017795789824552042248526932460448464213935446129034768931544855808205813233031778910586167456968043056337"
        "74403551026001843709276254508045501140094789013498338261024707804524802558382207231719552524121040060703220809"
        "32915859579006653276371401264439817338080069936810866666557553662506811",
        "0."
        "46407403288360522126660904671571257203469668709200603873826642103612288853249598361813813213381052968904786566"
        "92953779197875198551129732199199681897487094680751078691960227951470615447323659748048114951659729384412140500"
        "19644485997926354260821631204787568128329326062276101378173121400310640783339024253355707305651738832527542943"
        "19888872518149175050583958244086010074110878967984441526026195572046031",
        "0."
        "48070357880154616464768530714893198018226307768872832018696934136162055774617690112915494983829868655926209174"
        "89360967782384462897668266686108717492564982959216438017443396317004790075173581814272436867868360109175081998"
        "46583038060355729154999991805998725131730964293904561786424781897249037586982387229784063690841718040200402466"
        "31229610021517925007543961283845124822740019511921386188934760298241688",
        "0."
        "49716200000672278683141570737786924159326600032981923078600441023882683095816876734389429898823686013764499093"
        "45450791525321552887098982131873822779874559159792386492573308364057413255960311420668273948854145107727729158"
        "23576278813800080664406858374220095431847228987670874922641544998611124995909341089061963243930347786816222853"
        "46845867860458748417916763883649390228287689107774312170267691257606116",
        "0."
        "51344343749844216224309565441486087365890516381683759696704839526386373494321578458551193514743669178342420835"
        "08261186889101919380122376060422055215202801587825950917967223658687200416944237739334294136813668604421465633"
        "98795186912195162284347325371860283212459420769039289219296075028488886402670945904005562004022560897949544850"
        "61564115688273804254406706725374971267431122825004095102239220991848356",
        "0."
        "52954209528009218542956877037980380998240467111773187487177084701668417706002935457309027480414979338624119758"
        "86323328796923384578645911361995814665439710693337531208962600101135242417422341651511867090163901569989900501"
        "48869453239837976334718280493239177010684146991894718115080403237890477135362706172162492220748772918229207473"
        "92986535291960399633972613345908694327479738445245500914715996152461985",
        "0."
        "54545224242244689926647810432697721723945987179773365856990386707254353534614807468692870318816991084937065603"
        "19175427023977353192884886392626825442002063417490443992046573539958767940250304025163981504107216069602952896"
        "93737113750245240595359960775968445570117864118650717067667130499615153536644849965777519624745649686597551049"
        "83468313555304855249829815310291744255989014492588353749587481644931913",
        "0."
        "56116821510380861353700162760755101727268623115746212675907859515911800480855365905235006799852352328451502804"
        "87157760027718174057499497363513880321191207669596755880649398173345414890505444999165122707399661683590054260"
        "43672578436019959799441756846001365750989397641207459529643553535893175560674746809875275480792978335399982583"
        "42242865222215681747969549869015697939554127499557081626950060916329896",
        "0."
        "57668441862626054773920164705882295031880435874490231795930393597704964539534854834250638055542815083463738683"
        "14643008237907314907999895387197499060503053111574856790494822900253868046535181603441408589069619646761552196"
        "95430062242044339970635272885144434049354192539437245798724728543007037984759661075790388804966980518183755325"
        "46368197809806544115496171522444187250876233927302975709248591908972346",
        "0."
        "59199532940731223634617420193837196766186356068263223313261061480558639436412180991021350240470913092271149633"
        "48382090435094512722918016997607037947014742971101105620307821029831382963500056530378764199785793062943223127"
        "48702468361084527329930075411253597382734850613242287787505318300699445700361690848713053295152613659553831785"
        "02917713214334808810726412625844210978481512366368025275438632291862785",
        "0."
        "60709549694622869462483067245797028399468956070763942538530335526853282815406226053099893555611232739741099281"
        "19986342025433301618472031302488110001016175983708392879722472564002109578512598823899241029692722540998476588"
        "68633138738920225316489584519400836617158157608062378788036093306496951324738890465081604828877685737230883613"
        "32267243452286610176948724186843039692112797106039213976473403724518188",
        "0."
        "62197954576434335539696684219824327976988998993669475584026026679831221725774460365328908947620452777457191790"
        "80695993889905937938714039112884569698764241850661145332162660786980171787025483689732879616508460594808698394"
        "99447142264646447556445422380834033026615962392694762522226141098365973488734711907876603915856940787799213907"
        "58232910639208518119325492789999941075221166054973249356136808607130253",
        "0."
        "63664217731866404859201163181912040833896440981608280096667226355494770830393059049758136156431010608939993155"
        "09501318081025137289051787335454356108133761354485193083183997634369795655283340428506642872565827559825155045"
        "92493647078437855280056313635552649900255816201941027188071733864631847137568416344260183053761369162849847463"
        "2262547856029932241457937391840960919415488213025664314613747543749464",
        "0."
        "65107817188809080279752785471799265973958362274943758073000075578938519480042543196041314945170036193559782763"
        "52441315492761248959735514479956296341745596131088643179413243775735718537700771870979050497690033919155294496"
        "53088237548980799331864316936640158140105513673652937868065270349588736692115709061328490134974588199411686512"
        "27792824572805777219160376304646562062564773441718051418178414899683019",
        "0."
        "66528239043157399787665560528973471986510173497601386995195977335532785610133958511364589519832615972835853915"
        "02588949649092379467069209284755289821255744166256794329589771465045421874634188329764638118238723545310838064"
        "78564446808383799117236793588046206834703422289452407480899047603682163312792753222921340148646749652789369158"
        "8255513769781016943243185567913995336109327864083859254466073492381187",
        "0."
        "67924977641755138662041086036801948989088186294785002709809874961811116536667286127777672928127306388394020078"
        "45240241799383672298452390663130204781242580975928622023782635746506476509261210422483799207571103561565094277"
        "74542972359083080240539506356574880019160368012341165816711190698491333446640246775170757236606427092758234563"
        "43659009540444032487248071553674961012055521740306092600444870718199652",
        "0."
        "69297535762401272778114932738244728669670875114228232862389083194872888693112134130021641463393969624412179768"
        "29191440555457708035324713685998430794040137394052181591327446495096434762491844908164530454034316068338872701"
        "54897722024726454063182887492443341568578149274055287631085581374887942920573157159951913249645005286003782915"
        "62277858608403425720078390497455476055579003286296442406491998525563297",
        "0."
        "70645424790855122905182233963742667718470686911515869065744744473731249895412640632516625097411541437953942564"
        "56646831379807736685392860815416866866780693813066243922070201917232893688943632418730426224846333478750445680"
        "56830700260063077651787879970208891115566789078494425914787558006988084801632251257775118283523571892842171010"
        "98738405458071150544253514248561787426067001460586251699075230390564367",
        "0."
        "71968164894777168289159927814596788937422432901416956306230349431557362414856173295064125294878325237342190029"
        "91443077564866556014504059889811700097178397854179909228178100063390277962643786651728828432473282708306570344"
        "82796548006326241718617777105822936398798191169326805453135625250749408094036934756243321694587445623865800744"
        "20532959714281903926902622613852892104465683714186704831143197300465955",
        "0."
        "73265285194543608674851404628602868786755398311878599262050209465658337331457767882450516660833910207846986678"
        "48060305822132918550698396214430295016273750556209143264546699733465361807535937268052292257842951078310715522"
        "47428679792060038538934182680959364508238676238730155284531089445632765766465084121984979233834664708958087778"
        "76544429706485835161864475122029711660543090876323595451165397047981956",
        "0."
        "74536323930873866831066285008063416514858255428941319323031554151661731879818806472410911187787504167842137286"
        "01902026400847169260703087210502048987440263152482376744843291543822533586962209335453802100631453619846913663"
        "43648500427157756213079655245603089013975508296108511250725188848225159266262135819491900242687118270235220128"
        "04341871590177804438418738255381261594827085100659777173578154500251787",
        "0."
        "75780828629211358196731753685850074775187628883294491833833279769413437275246840580617185041212744084038976069"
        "70014288703593751130941949551239008908784777565183336917338603851333025748018820469668713623126759539943834315"
        "68950326824953277403282917383252177784974732604637406008529736002979132389588281323360806240488155741134145925"
        "22918778477418427876829087439774857073733879539765547872800792711360592",
        "0."
        "76998356260799010064124325420889481428942836988785464918451704687709959533402569414853910266075223008145347866"
        "42046985222099747099298718359513471127816199482701048247866652319991470745736568197998941719917742780812930885"
        "02285957266324681395273169154817094659382576501207939346854213434439423560603962910757527134804023056991209647"
        "04579260218579751719693291565685728074939857101460901984240449471777639",
        "0."
        "78188473400392189344901888012886357289691591193533323711550248487573232160560048524966536928562079994581390209"
        "19252650989917607739386224548280716556940903694314677593109095804194531748935102050618095795948293976827585139"
        "81308929705574507831389835663924552709042280571754890979673148712991508327126326397188787024716586063695408544"
        "96281803565819545728647765960328269135853132407415684491934581417388002",
        "0."
        "79350756380552895006859336306152006552993066088382163294295016384877329185292344719536879395060919553184640006"
        "47387595525733026481311592994287715689443323387616157389462894445274008065393508928915317383633404037443136085"
        "03368514245746686328373380167403337165309634342914896450179310355290525874836291111789719174211213987325800601"
        "01294617212337648611654041575132820234403350225337355214099696493406567",
        "0."
        "80484791442470288298134387731514331459831415420391927496917008531718727007136925375073869996549995938671025493"
        "75598780231680756067275420552291634154795052741628500944706563229622092496460337010974726670013661883276781393"
        "82437847590730355550353619117721696871119722942620960813936566540675127858271396083675600092987218192810910107"
        "43363153063005841441400130721362346287552727162527118465104052539630019",
        "0."
        "81590174883253870457705586780548750833668862852238889952372206236774966573191832400412494946116015154305873210"
        "75996324785943168839319282924870053583761216724263389662729282166689081973654965253473810701287309481282521960"
        "14898800604919583855529794766210042360994900188876511863470866753816038010179408082908553408703836830754091224"
        "77045713172106217670870448929077822708030574128623585863036730829850118",
    }};

    max_err = 0;
    for (unsigned k = 0; k < small_data.size(); k++) {
        static const T euler_gamma = static_cast<T>(
            "5."
            "7721566490153286060651209008240243104215933593992359880576723488486772677766467093694706329174674951463144"
            "7249807082480960504014486542836224173997644923536253500333742937337737673942792595258247094916008735203948"
            "165670853233151776611528621199501507984793745085705740029921354786146694029604325421519e-1");
        T val = sin((euler_gamma + k) / 53);
        T e = relative_error(val, T(small_data[k]));
        unsigned err = e.template convert_to<unsigned>();
        if (err > max_err) {
            max_err = err;
        }
        val = sin(-(euler_gamma + k) / 53);
        e = relative_error(val, T(-T(small_data[k])));
        err = e.template convert_to<unsigned>();
        if (err > max_err)
            max_err = err;
    }
    std::cout << "Max error was: " << max_err << std::endl;
    BOOST_TEST(max_err < 20);

    //
    // Test with some exact binary values as input - this tests our code
    // rather than the test data:
    //
    static const boost::array<boost::array<T, 2>, 9> exact_data = {
        {{{0.5, static_cast<T>("0."
                               "479425538604203000273287935215571388081803367940600675188616613125535000287814832209631"
                               "274684348269086132091084505717418")}},
         {{0.25, static_cast<T>("0."
                                "24740395925452292959684870484938919589339098038696581067654483049439813604348682169098"
                                "4848527973792338327197752176516138")}},
         {{0.75, static_cast<T>("0."
                                "68163876002333416673324195277989393533838239465922990921362526215110038888700378275314"
                                "5274849781911981438190343146876189")}},
         {{std::ldexp(1.0, -20), static_cast<T>("9."
                                                "5367431640610543971033527264930654980150669873983875388881578748970711"
                                                "4648106832493113326022411646219016312547902694921e-7")}},
         {{2, static_cast<T>("0."
                             "90929742682568169539601986591174484270225497144789026837897301153096730154078354462012668"
                             "8924959380309967896742399486261")}},
         {{5, static_cast<T>("-0."
                             "95892427466313846889315440615599397335246154396460177813167245423510255808655960307699595"
                             "5429532866596530638461663378937")}},
         {{10, static_cast<T>("-0."
                              "5440211108893698134047476618513772816836430129162238915741840126167572096404934257070756"
                              "73894983216158293824238262832286")}},
         {{0, 0}},
         {{static_cast<T>(
               "1."
               "5707963267948966192313216916397514420985846996875529104874722961539082031431044993140174126710585339910"
               "7404325664115332354692230477529111586267970406424055872514205135096926055277982231147447746519098221440"
               "548783296672306423782411689339158263560095457282428346173017430522716332410669680363012457064"),
           1}}}};
    max_err = 0;
    for (unsigned k = 0; k < exact_data.size(); k++) {
        T val = sin(exact_data[k][0]);
        T e = relative_error(val, exact_data[k][1]);
        unsigned err = e.template convert_to<unsigned>();
        if (err > max_err)
            max_err = err;
    }
    std::cout << "Max error was: " << max_err << std::endl;
    BOOST_TEST(max_err < 20);

#include "sincos.ipp"
    max_err = 0;
    for (unsigned k = 0; k < sincos.size(); k++) {
        T val = sin(sincos[k][0]);
        T e = relative_error(val, sincos[k][1]);
        unsigned err = e.template convert_to<unsigned>();
        if (err > max_err)
            max_err = err;
    }
    std::cout << "Max error was: " << max_err << std::endl;
    BOOST_TEST(max_err < 20);

    if (has_poor_large_value_support<T>::value) {
        T bug_value = 12 / std::numeric_limits<T>::epsilon();
        for (unsigned i = 0; i < 20; ++i, bug_value *= 1.1) {
            BOOST_TEST(sin(bug_value) == 0);
        }
    }
}

int main() {
#ifdef TEST_BACKEND
    test<
        nil::crypto3::multiprecision::number<nil::crypto3::multiprecision::concepts::number_backend_float_architype>>();
#endif
#ifdef TEST_MPF_50
    test<nil::crypto3::multiprecision::mpf_float_50>();
    test<nil::crypto3::multiprecision::mpf_float_100>();
#endif
#ifdef TEST_MPFR_50
    test<nil::crypto3::multiprecision::mpfr_float_50>();
    test<nil::crypto3::multiprecision::mpfr_float_100>();
#endif
#ifdef TEST_MPFI_50
    test<nil::crypto3::multiprecision::mpfi_float_50>();
    test<nil::crypto3::multiprecision::mpfi_float_100>();
#endif
#ifdef TEST_CPP_DEC_FLOAT
    test<nil::crypto3::multiprecision::cpp_dec_float_50>();
    test<nil::crypto3::multiprecision::cpp_dec_float_100>();
#ifndef SLOW_COMPLER
    // Some "peculiar" digit counts which stress our code:
    test<nil::crypto3::multiprecision::number<nil::crypto3::multiprecision::cpp_dec_float<65>>>();
    test<nil::crypto3::multiprecision::number<nil::crypto3::multiprecision::cpp_dec_float<64>>>();
    test<nil::crypto3::multiprecision::number<nil::crypto3::multiprecision::cpp_dec_float<63>>>();
    test<nil::crypto3::multiprecision::number<nil::crypto3::multiprecision::cpp_dec_float<62>>>();
    test<nil::crypto3::multiprecision::number<nil::crypto3::multiprecision::cpp_dec_float<61, long long>>>();
    test<nil::crypto3::multiprecision::number<nil::crypto3::multiprecision::cpp_dec_float<60, long long>>>();
    test<nil::crypto3::multiprecision::number<
        nil::crypto3::multiprecision::cpp_dec_float<59, long long, std::allocator<char>>>>();
    test<nil::crypto3::multiprecision::number<
        nil::crypto3::multiprecision::cpp_dec_float<58, long long, std::allocator<char>>>>();
    // Check low multiprecision digit counts.
    test<nil::crypto3::multiprecision::number<nil::crypto3::multiprecision::cpp_dec_float<9>>>();
    test<nil::crypto3::multiprecision::number<nil::crypto3::multiprecision::cpp_dec_float<18>>>();
#endif
#endif
#ifdef TEST_FLOAT128
    test<nil::crypto3::multiprecision::float128>();
#endif
#ifdef TEST_CPP_BIN_FLOAT
    test<nil::crypto3::multiprecision::cpp_bin_float_50>();
    test<nil::crypto3::multiprecision::number<nil::crypto3::multiprecision::cpp_bin_float<
        35, nil::crypto3::multiprecision::digit_base_10, std::allocator<char>, boost::long_long_type>>>();
#endif
    return boost::report_errors();
}
